package com.hhl.lamda.test20240411;

import com.hhl.lamda.entity.Employee;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: HHL
 * @Date: 2024/4/11 10:56
 * @Description: A01
 * @Version 1.0.0
 */
public class A01 {
    public static void main(String[] args) {

        List<Employee> employeeList = Arrays.asList(
            new Employee(102, "李四", 60, 6666.66, "BUSY"),
            new Employee(102, "张三", 18, 9999.99, "FREE"),
            new Employee(103, "王五", 28, 3333.33, "VOCATION"),
            new Employee(104, "赵六", 8, 7777.77, "BUSY"),
            new Employee(104, "赵六", 8, 7777.77, "FREE"),
            new Employee(104, "赵六", 8, 7777.77, "FREE"),
            new Employee(106, "田七", 38, 5555.55, "BUSY")
        );


        // 1、需求：获取公司中年龄小于 35 的员工信息
        List<Employee> empAgeLt35 = employeeList.stream().filter(emp -> emp.getAge() < 35).collect(Collectors.toList());
        // [Employee [id=101, name=张三, age=18, salary=9999.99], Employee [id=103, name=王五, age=28, salary=3333.33], Employee [id=104, name=赵六, age=8, salary=7777.77]]
        System.out.println(empAgeLt35);


        // 2、需求：获取公司中工资大于 5000 的员工信息
        List<Employee> employeeSalGt5000 = employeeList.stream().filter(employee -> employee.getSalary() > 5000).collect(Collectors.toList());
        // [Employee [id=101, name=张三, age=18, salary=9999.99], Employee [id=102, name=李四, age=59, salary=6666.66], Employee [id=104, name=赵六, age=8, salary=7777.77], Employee [id=105, name=田七, age=38, salary=5555.55]]
        System.out.println(employeeSalGt5000);


        // 3、根据姓名进行排序
        List<String> collect = employeeList.stream().map(Employee::getName).sorted().collect(Collectors.toList());
        // [张三, 李四, 王五, 田七, 赵六]
        System.out.println(collect);


        /**
         * 4、终止操作
         * 		allMatch——检查是否匹配所有元素
         * 		anyMatch——检查是否至少匹配一个元素
         * 		noneMatch——检查是否没有匹配的元素
         * 		findFirst——返回第一个元素
         * 		findAny——返回当前流中的任意元素
         * 		count——返回流中元素的总个数
         * 		max——返回流中最大值
         * 		min——返回流中最小值
         */
        // allMatch——判断数据集合中全部元素都符合元素设置的predicate条件( boolean allMatch(Predicate predicate);)，如满足就返回true，否则返回false
        boolean allMatch = employeeList.stream().allMatch(employee -> "BUSY".equals(employee.getStatus()));
        // 集合中所有元素的Status属性满足条件(状态等于“BUSY”)，不满足就返回false
        // false
        System.out.println(allMatch);


        // anyMatch——判断数据集合中是否存在任意一个元素符合设置的predicate条件( [boolean] anyMatch(Predicate predicate);)，如存在就返回true，否则返回false
        boolean anyMatch = employeeList.stream().anyMatch(employee -> "BUSY".equals(employee.getStatus()));
        // 集合中任意一个元素的Status属性满足条件(状态等于“BUSY”)，不满足就返回false
        // true
        System.out.println(anyMatch);


        // noneMatch——判断数据集合中全部元素都不符合设置的predicate条件( boolean noneMatch(Predicate predicate);)，如全部不符合返回true，否则返回false
        boolean noneMatch = employeeList.stream().noneMatch(employee -> "BUSY".equals(employee.getStatus()));
        // 全部元素不满足Status属性满足条件(状态等于“BUSY”)，有满足的则返回false。
        // false
        System.out.println(noneMatch);


        // findFirst——返回第一个元素，流findFirst()返回描述此流的第一个元素的Optional(一个容器对象，可能包含或可能不包含非null值)；如果该流为空，则返回空的Optional。如果流没有遇到顺序，则可以返回任何元素。
        Optional<Employee> findFirst = employeeList.stream().filter(employee -> "BUSY".equals(employee.getStatus())).findFirst();
        // Employee{id=102, name='李四', age=59, salary=6666.66, status='BUSY'}
        System.out.println(findFirst.get());


        // findAny——返回当前流中的任意元素,findAny()是流接口的terminal-short-circuiting操作。此方法返回满足中间操作的第一个元素
        Optional<Employee> findAny = employeeList.stream().filter(employee -> "FREE".equals(employee.getStatus())).findAny();
        // Optional[Employee{id=101, name='张三', age=18, salary=9999.99, status='FREE'}]
        System.out.println(findAny);


        // counting——返回流中元素的总个数
        Long aLong = employeeList.stream().filter(employee -> "BUSY".equals(employee.getStatus())).collect(Collectors.counting());
        // 3
        System.out.println(aLong);


        // count——返回流中元素的总个数
        long count = employeeList.stream().filter(employee -> "BUSY".equals(employee.getStatus())).count();
        // // 3
        System.out.println(count);


        // maxBy——获取列表中符合条件的Age属性值最大的对象元素
        Optional<Employee> employeeMaxByOptional = employeeList.stream().filter(employee -> "BUSY".equals(employee.getStatus())).collect(Collectors.maxBy(Comparator.comparingInt(Employee::getAge)));
        // Employee{id=102, name='李四', age=59, salary=6666.66, status='BUSY'}
        System.out.println(employeeMaxByOptional.get());


        // max——返回流中最大Salary属性值
        Optional<Double> maxSalaryOptional = employeeList.stream().map(Employee::getSalary).max(Double::compareTo);
        // Optional[9999.99]
        System.out.println(maxSalaryOptional);


        // 获取列表中的Salary属性值最大的对象元素
        Optional<Employee> max = employeeList.stream().max((epm1, emp2) -> Double.compare(epm1.getSalary(), emp2.getSalary()));
        // Optional[Employee{id=101, name='张三', age=18, salary=9999.99, status='FREE'}]
        System.out.println(max);


        // minBy——获取列表中符合条件的Age属性值最小的对象元素
        Optional<Employee> employeeMinByOptional = employeeList.stream().filter(employee -> "BUSY".equals(employee.getStatus())).collect(Collectors.minBy(Comparator.comparingInt(Employee::getAge)));
        // Optional[Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'}]
        System.out.println(employeeMinByOptional);


        // min——返回流中最小Salary值
        Optional<Double> minSalaryOptional = employeeList.stream().map(Employee::getSalary).min(Double::compareTo);
        // 3333.33
        System.out.println(minSalaryOptional.get());


        // 获取列表中的Salary属性值最小的对象元素
        Optional<Employee> min = employeeList.stream().min((emp1, emp2) -> Double.compare(emp1.getSalary(), emp2.getSalary()));
        // Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'}
        System.out.println(min.get());


        /****************************************************************************************************************************************/


        List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");

        // 将所有字母编号变成大写并打印输出
        Stream<String> stringStream = strList.stream().map(String::toUpperCase);
        /**
         * AAA
         * BBB
         * CCC
         * DDD
         * EEE
         */
        stringStream.forEach(System.out::println);


        // 将所有字母编号变成大写并变成一个集合
        List<String> strings = strList.stream().map(String::toUpperCase).collect(Collectors.toList());
        // [AAA, BBB, CCC, DDD, EEE]
        System.out.println(strings);


        /****************************************************************************************************************************************/


        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,1);


        // 可以将流中元素反复结合起来，得到一个值
        Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
        // 46
        System.out.println(reduce);


        Optional<Integer> integerOptional = list.stream().reduce(Integer::sum);
        // 46
        System.out.println("integerOptional===" + integerOptional.get());


        // 可以将流中元素反复结合起来，得到一个值
        Optional<Double> doubleSalaryOptional = employeeList.stream().map(Employee::getSalary).reduce(Double::sum);
        // 48888.84000000001
        System.out.println(doubleSalaryOptional.get());


        List<String> nameList = employeeList.stream().map(Employee::getName).collect(Collectors.toList());
        // [李四, 张三, 王五, 赵六, 赵六, 赵六, 田七]
        System.out.println(nameList);


        Set<String> nameSet = employeeList.stream().map(Employee::getName).collect(Collectors.toSet());
        // [李四, 张三, 王五, 赵六, 田七]
        System.out.println(nameSet);


        // 把流中元素收集到Map---想获得一个age和salary对应的Map<String, String>
        Map<Integer, Double> toMapCollect = employeeList.stream().distinct().collect(Collectors.toMap(Employee::getAge, Employee::getSalary));
        // {18=9999.99, 38=5555.55, 8=7777.77, 59=6666.66, 28=3333.33}
        System.out.println(toMapCollect);


        ArrayList<String> nameArrayList = employeeList.stream().map(Employee::getName).collect(Collectors.toCollection(ArrayList::new));
        // [李四, 张三, 王五, 赵六, 赵六, 赵六, 田七]
        System.out.println(nameArrayList);


        String collectJoining = employeeList.stream().map(Employee::getName).collect(Collectors.joining());
        // 李四张三王五赵六赵六赵六田七
        System.out.println(collectJoining);


        String collectJoiningSep = employeeList.stream().map(Employee::getName).collect(Collectors.joining(","));
        // 李四,张三,王五,赵六,赵六,赵六,田七
        System.out.println(collectJoiningSep);


        HashSet<String> nameHashSet = employeeList.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
        // [李四, 张三, 王五, 赵六, 田七]
        System.out.println(nameHashSet);


        Optional<Double> optionalDouble = employeeList.stream().map(Employee::getSalary).collect(Collectors.maxBy(Double::compareTo));
        // 9999.99
        System.out.println(optionalDouble.get());


        Optional<Double> max1 = employeeList.stream().map(Employee::getSalary).max(Double::compareTo);
        // 9999.99
        System.out.println(max1.get());


        Optional<Employee> max2 = employeeList.stream().max((emp1, emp2) -> Double.compare(emp1.getSalary(), emp2.getSalary()));
        // Employee{id=101, name='张三', age=18, salary=9999.99, status='FREE'}
        System.out.println(max2.get());


        Optional<Double> min1 = employeeList.stream().map(Employee::getSalary).collect(Collectors.minBy(Double::compareTo));
        // 3333.33
        System.out.println(min1.get());


        Optional<Double> min2 = employeeList.stream().map(Employee::getSalary).min(Double::compareTo);
        // 3333.33
        System.out.println(min2.get());


        Optional<Employee> min3 = employeeList.stream().min((emp1, emp2) -> Double.compare(emp1.getSalary(), emp2.getSalary()));
        // Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'}
        System.out.println(min3.get());


        DoubleSummaryStatistics doubleSummaryStatistics = employeeList.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
        // 48888.840000000004
        System.out.println(doubleSummaryStatistics.getSum());
        // 9999.99
        System.out.println(doubleSummaryStatistics.getMax());
        // 6984.120000000001
        System.out.println(doubleSummaryStatistics.getAverage());
        // 7
        System.out.println(doubleSummaryStatistics.getCount());
        // 3333.33
        System.out.println(doubleSummaryStatistics.getMin());


        Double collect1 = employeeList.stream().collect(Collectors.summingDouble(Employee::getSalary));
        // 48888.840000000004
        System.out.println(collect1);


        Double collect2 = employeeList.stream().collect(Collectors.averagingDouble(Employee::getSalary));
        // 6984.120000000001
        System.out.println(collect2);


        Map<String, List<Employee>> collect3 = employeeList.stream().collect(Collectors.groupingBy(Employee::getName));
        /**
         * {
         * 李四=[Employee{id=102, name='李四', age=59, salary=6666.66, status='BUSY'}],
         * 张三=[Employee{id=101, name='张三', age=18, salary=9999.99, status='FREE'}],
         * 王五=[Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'}],
         * 赵六=[Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'},
         *      Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'},
         *      Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}],
         * 田七=[Employee{id=105, name='田七', age=38, salary=5555.55, status='BUSY'}]
         * }
         */
        System.out.println(collect3);


        Map<Boolean, List<Employee>> booleanListMap = employeeList.stream().collect(Collectors.partitioningBy(employee -> employee.getSalary() > 6000));
        /**
         * {
         * false=[Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'},
         *       Employee{id=105, name='田七', age=38, salary=5555.55, status='BUSY'}],
         *
         * true=[Employee{id=102, name='李四', age=59, salary=6666.66, status='BUSY'},
         *      Employee{id=101, name='张三', age=18, salary=9999.99, status='FREE'},
         *      Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'},
         *      Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'},
         *      Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}]
         * }
         */
        System.out.println(booleanListMap);



        String collect4 = employeeList.stream().map(Employee::getName).collect(Collectors.joining(",", "------", "********"));
        // ------李四,张三,王五,赵六,赵六,赵六,田七********
        System.out.println(collect4);


        Optional<Double> collect5 = employeeList.stream().map(Employee::getSalary).collect(Collectors.reducing(Double::sum));
        // 48888.84000000001
        System.out.println(collect5.get());


        // 从一个作为累加器的初始值开始，利用BinaryOperator与流中元素逐个结合，从而归约成单个值
        Integer reducingCollect = employeeList.stream().collect(Collectors.reducing(0, Employee::getAge, Integer::sum));
        // 168
        System.out.println(reducingCollect);


        /****************************************************************************************************************************************/


        // 把流中元素收集到List
        List<Employee> collect6 = employeeList.stream().collect(Collectors.toList());
        // [Employee{id=102, name='李四', age=59, salary=6666.66, status='BUSY'}, Employee{id=101, name='张三', age=18, salary=9999.99, status='FREE'}, Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'}, Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'}, Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}, Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}, Employee{id=105, name='田七', age=38, salary=5555.55, status='BUSY'}]
        System.out.println(collect6);


        // 把流中元素收集到Set
        Set<Employee> collect7 = employeeList.stream().collect(Collectors.toSet());
        // [Employee{id=102, name='李四', age=59, salary=6666.66, status='BUSY'}, Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'}, Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'}, Employee{id=105, name='田七', age=38, salary=5555.55, status='BUSY'}, Employee{id=101, name='张三', age=18, salary=9999.99, status='FREE'}]
        System.out.println(collect7);


        // 把流中元素收集到Map---想获得一个age和salary对应的Map<String, String>
        Map<Integer, Double> collect8 = employeeList.stream().distinct().collect(Collectors.toMap(Employee::getAge, Employee::getSalary));
        // {18=9999.99, 38=5555.55, 8=7777.77, 59=6666.66, 28=3333.33}
        System.out.println(collect8);


        // 把流中元素收集到创建的集合
        ArrayList<Employee> collect9 = employeeList.stream().collect(Collectors.toCollection(ArrayList::new));
        // [Employee{id=102, name='李四', age=59, salary=6666.66, status='BUSY'}, Employee{id=101, name='张三', age=18, salary=9999.99, status='FREE'}, Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'}, Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'}, Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}, Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}, Employee{id=105, name='田七', age=38, salary=5555.55, status='BUSY'}]
        System.out.println(collect9);


        // 计算流中元素的个数
        Long collect10 = employeeList.stream().collect(Collectors.counting());
        // 7
        System.out.println(collect10);


        // 对流中元素的整数属性求和
        Integer collect11 = employeeList.stream().collect(Collectors.summingInt(Employee::getAge));
        // 168
        System.out.println(collect11);


        // 计算流中元素Integer属性的平均值
        Double collect12 = employeeList.stream().collect(Collectors.averagingInt(Employee::getAge));
        // 23.857142857142858
        System.out.println(collect12);


        // 收集流中Integer属性的统计值。如：平均值
        IntSummaryStatistics collect13 = employeeList.stream().collect(Collectors.summarizingInt(Employee::getAge));
        // 59
        System.out.println(collect13.getMax());
        // 23.857142857142858
        System.out.println(collect13.getAverage());
        // 7
        System.out.println(collect13.getCount());
        // 8
        System.out.println(collect13.getMin());
        // 168
        System.out.println(collect13.getSum());


        // 连接流中每个字符串
        String collect14 = employeeList.stream().map(Employee::getName).collect(Collectors.joining());
        // 李四张三王五赵六赵六赵六田七
        System.out.println(collect14);


        String collect15 = employeeList.stream().map(Employee::getName).collect(Collectors.joining(","));
        // 李四,张三,王五,赵六,赵六,赵六,田七
        System.out.println(collect15);


        String collect16 = employeeList.stream().map(Employee::getName).collect(Collectors.joining(",", "-------", "********"));
        // -------李四,张三,王五,赵六,赵六,赵六,田七********
        System.out.println(collect16);


        // 根据比较器选择最大值
        Optional<Employee> collect17 = employeeList.stream().collect(Collectors.maxBy(Comparator.comparingInt(Employee::getAge)));
        // Employee{id=102, name='李四', age=60, salary=6666.66, status='BUSY'}
        System.out.println(collect17.get());


        Optional<Integer> max3 = employeeList.stream().map(Employee::getAge).max(Integer::compareTo);
        // 60
        System.out.println(max3.get());


        Optional<Employee> collect18 = employeeList.stream().collect(Collectors.maxBy((emp1, emp2) -> Integer.compare(emp1.getAge(), emp2.getAge())));
        // Employee{id=102, name='李四', age=60, salary=6666.66, status='BUSY'}
        System.out.println(collect18.get());


        // 根据比较器选择最小值
        Optional<Integer> collect19 = employeeList.stream().map(Employee::getAge).collect(Collectors.minBy(Integer::compareTo));
        // 8
        System.out.println(collect19.get());


        Optional<Integer> min4 = employeeList.stream().map(Employee::getAge).min(Integer::compareTo);
        // 8
        System.out.println(min4.get());


        Optional<Employee> collect20 = employeeList.stream().collect(Collectors.minBy((emp1, emp2) -> Integer.compare(emp1.getAge(), emp2.getAge())));
        // Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'}
        System.out.println(collect20.get());


        // 从一个作为累加器的初始值开始，利用BinaryOperator与流中元素逐个结合，从而归约成单个值
        Integer collect21 = employeeList.stream().collect(Collectors.reducing(0, Employee::getAge, Integer::sum));
        // 168
        System.out.println(collect21);


        // 包裹另一个收集器，对其结果转换函数
        Integer collect22 = employeeList.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
        // 7
        System.out.println(collect22);


        // 根据某属性值对流分组，属性值为K，结果为V
        Map<String, List<Employee>> collect23 = employeeList.stream().collect(Collectors.groupingBy(Employee::getStatus));
        /**
         * {
         * BUSY=[
         *          Employee{id=102, name='李四', age=60, salary=6666.66, status='BUSY'},
         *          Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'},
         *          Employee{id=106, name='田七', age=38, salary=5555.55, status='BUSY'}
         *      ],
         * VOCATION=[Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'}],
         * FREE=[
         *          Employee{id=102, name='张三', age=18, salary=9999.99, status='FREE'},
         *          Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'},
         *          Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}
         *      ]
         * }
         */
        System.out.println(collect23);


        // 根据true或false进行分区
        Map<Boolean, List<Employee>> collect24 = employeeList.stream().collect(Collectors.partitioningBy(employee -> employee.getSalary() > 6000));
        /**
         * {
         * false=[
         *          Employee{id=103, name='王五', age=28, salary=3333.33, status='VOCATION'},
         *          Employee{id=106, name='田七', age=38, salary=5555.55, status='BUSY'}
         *      ], 
         * true=[
         *          Employee{id=102, name='李四', age=60, salary=6666.66, status='BUSY'}, 
         *          Employee{id=102, name='张三', age=18, salary=9999.99, status='FREE'}, 
         *          Employee{id=104, name='赵六', age=8, salary=7777.77, status='BUSY'}, 
         *          Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}, 
         *          Employee{id=104, name='赵六', age=8, salary=7777.77, status='FREE'}
         *      ]
         * }
         */
        System.out.println(collect24);
    }
}
